﻿using UnityEngine;
using System.Collections;
using System;
using UnityEngine.UI;
using IndieStudio.BugsBang.Game;

///Developed By Indie Studio
///https://assetstore.unity.com/publishers/9268
///www.indiestd.com
///info@indiestd.com

namespace IndieStudio.BugsBang.Utility
{
	public class CommonUtil
	{
		/// <summary>
		/// Set the size for the UI element.
		/// </summary>
		/// <param name="trans">The Rect transform referenced.</param>
		/// <param name="newSize">The New size.</param>
		public static void SetSize (RectTransform trans, Vector2 newSize)
		{
			Vector2 oldSize = trans.rect.size;
			Vector2 deltaSize = newSize - oldSize;
			trans.offsetMin = trans.offsetMin - new Vector2 (deltaSize.x * trans.pivot.x, deltaSize.y * trans.pivot.y);
			trans.offsetMax = trans.offsetMax + new Vector2 (deltaSize.x * (1f - trans.pivot.x), deltaSize.y * (1f - trans.pivot.y));
		}

		/// <summary>
		/// True the false to On/Off text.
		/// </summary>
		/// <returns>The On/Off text.</returns>
		/// <param name="value">flag value.</param>
		public static string TrueFalseToOnOff (bool value)
		{
			if (value) {
				return "On";
			}
			return "Off";
		}

		/// <summary>
		/// Converts bool value true/false to int value 0/1.
		/// </summary>
		/// <returns>The int value.</returns>
		/// <param name="value">The bool value.</param>
		public static int TrueFalseBoolToZeroOne (bool value)
		{
			if (value) {
				return 1;
			}
			return 0;
		}

		/// <summary>
		/// Converts int value 0/1 to bool value true/false.
		/// </summary>
		/// <returns>The bool value.</returns>
		/// <param name="value">The int value.</param>
		public static bool ZeroOneToTrueFalseBool (int value)
		{
			if (value == 0) {
				return false;
			} else {
				return true;
			}
		}

		/// <summary>
		/// Converts string value 0/1 to bool value true/false.
		/// </summary>
		/// <returns>The bool value.</returns>
		/// <param name="value">The string value.</param>
		public static bool ZeroOneToTrueFalseBool (string value)
		{
			if (value == "0") {
				return false;
			} else {
				return true;
			}
		}

		/// <summary>
		/// Converts Strings to integer.
		/// </summary>
		/// <returns>The int value.</returns>
		/// <param name="value">String value.</param>
		public static int StringToInt(string value){
			int result = 0;
			int.TryParse (value, out result);
			return result;
		}

		/// <summary>
		/// Converts from enum StarsNumber to int number value.
		/// </summary>
		/// <returns>The stars number as int.</returns>
		/// <param name="starsNumber">Stars number enum.</param>
		public static int LevelStarsNumberEnumToIntNumber (LevelsManager.Level.StarsNumber starsNumber)
		{
			if (starsNumber == LevelsManager.Level.StarsNumber.ZERO) {
				return 0;
			} else if (starsNumber == LevelsManager.Level.StarsNumber.ONE) {
				return 1;
			} else if (starsNumber == LevelsManager.Level.StarsNumber.TWO) {
				return 2;
			} else if (starsNumber == LevelsManager.Level.StarsNumber.THREE) {
				return 3;
			}

			return -1;//undefined
		}

		/// <summary>
		/// Converts from int number value to enum StarsNumber.
		/// </summary>
		/// <returns>The stars number as enum.</returns>
		/// <param name="starsNumber">Stars number as int.</param>
		public static  LevelsManager.Level.StarsNumber IntNumberToLevelStarsNumberEnum (int starsNumber)
		{
			if (starsNumber == 1) {
				return  LevelsManager.Level.StarsNumber.ONE;
			} else if (starsNumber == 2) {
				return  LevelsManager.Level.StarsNumber.TWO;
			} else if (starsNumber == 3) {
				return  LevelsManager.Level.StarsNumber.THREE;
			} else {
				return  LevelsManager.Level.StarsNumber.ZERO;
			}
		}


		/// <summary>
		/// Converts from string number value to enum StarsNumber.
		/// </summary>
		/// <returns>The stars number as enum.</returns>
		/// <param name="starsNumber">Stars number as string.</param>
		public static  LevelsManager.Level.StarsNumber IntNumberToLevelStarsNumberEnum (string starsNumber)
		{
			if (starsNumber == "1") {
				return  LevelsManager.Level.StarsNumber.ONE;
			} else if (starsNumber == "2") {
				return  LevelsManager.Level.StarsNumber.TWO;
			} else if (starsNumber == "3") {
				return  LevelsManager.Level.StarsNumber.THREE;
			} else {
				return  LevelsManager.Level.StarsNumber.ZERO;
			}
		}

		/// <summary>
		/// Set the stars rating for a set of stars.
		/// </summary>
		/// <param name="starsNumber">Stars number.</param>
		/// <param name="starOne">Star one image.</param>
		/// <param name="starTwo">Star two image.</param>
		/// <param name="starThree">Star three image.</param>
		/// <param name="starOn">Star on sprite.</param>
		/// <param name="starOff">Star off sprite.</param>
		public static void SetStarsRating (LevelsManager.Level.StarsNumber starsNumber, Image starOne, Image starTwo, Image starThree, Sprite starOn, Sprite starOff)
		{
			if (starOne == null || starTwo == null || starThree == null) {
				return;
			}

			//Apply the current Stars Rating 
			if (starsNumber == LevelsManager.Level.StarsNumber.ONE) {//One Star
				starOne.sprite = starOn;
				starTwo.sprite = starOff;
				starThree.sprite = starOff;
			} else if (starsNumber == LevelsManager.Level.StarsNumber.TWO) {//Two Stars
				starOne.sprite = starOn;
				starTwo.sprite = starOn;
				starThree.sprite = starOff;
			} else if (starsNumber == LevelsManager.Level.StarsNumber.THREE) {//Three Stars
				starOne.sprite = starOn;
				starTwo.sprite = starOn;
				starThree.sprite = starOn;
			} else {//Zero Stars
				starOne.sprite = starOff;
				starTwo.sprite = starOff;
				starThree.sprite = starOff;
			}
		}

		/// <summary>
		/// Set the stars rating for a set of stars.
		/// </summary>
		/// <param name="starsNumber">Stars number.</param>
		/// <param name="starOne">Star one image.</param>
		/// <param name="starTwo">Star two image.</param>
		/// <param name="starThree">Star three image.</param>
		public static void SetStarsRating (LevelsManager.Level.StarsNumber starsNumber, Transform starOne, Transform starTwo, Transform starThree)
		{
			if (starOne == null || starTwo == null || starThree == null) {
				return;
			}

			int starsCount =LevelStarsNumberEnumToIntNumber(starsNumber);

			//Apply the current Stars Rating 
			starOne.Find ("StarOn").gameObject.SetActive (starsCount > 0 ? true : false);
			starTwo.Find ("StarOn").gameObject.SetActive (starsCount > 1 ? true : false);
			starThree.Find ("StarOn").gameObject.SetActive (starsCount > 2 ? true : false);
		}

		/// <summary>
		/// Converts RGBA string to RGBA Color , seperator is ',' 
		/// </summary>
		/// <returns>The RGBA Color.</returns>
		/// <param name="rgba">rgba string.</param>
		public static Color StringRGBAToColor (string rgba)
		{
			Color color = Color.clear;

			if (!string.IsNullOrEmpty (rgba)) {
				try {
					string[] rgbaValues = rgba.Split (',');
					float red = float.Parse (rgbaValues [0]);
					float green = float.Parse (rgbaValues [1]);
					float blue = float.Parse (rgbaValues [2]);
					float alpha = float.Parse (rgbaValues [3]);

					color.r = red;
					color.g = green;
					color.b = blue;
					color.a = alpha;
				} catch (Exception ex) {
					Debug.Log (ex.Message);
				}
			}
			return color;
		}


		/// <summary>
		/// Convert Integer value to custom string format.
		/// </summary>
		/// <returns>The to string.</returns>
		/// <param name="value">Value.</param>
		public static string IntToString (int value)
		{
			if (value < 10) {
				return "0" + value;
			}
			return value.ToString ();
		}

		/// <summary>
		/// Enable the childern of the given gameobject.
		/// </summary>
		/// <param name="gameObject">The Gameobject reference.</param>
		public static void EnableChildern (Transform gameObject)
		{
			if (gameObject == null) {
				return;
			}
				
			foreach (Transform child in gameObject) {
				child.gameObject.SetActive (true);
			}
		}

		/// <summary>
		/// Disable the childern of the given gameobject.
		/// </summary>
		/// <param name="gameObject">The Gameobject reference.</param>
		public static void DisableChildern (Transform gameObject)
		{
			if (gameObject == null) {
				return;
			}
			
			foreach (Transform child in gameObject) {
				child.gameObject.SetActive (false);
			}
		}

		/// <summary>
		/// Find the game objects of tag.
		/// </summary>
		/// <returns>The game objects of tag(Sorted by name).</returns>
		/// <param name="tag">Tag.</param>
		public static GameObject[] FindGameObjectsOfTag (string tag)
		{
			GameObject[] gameObjects = GameObject.FindGameObjectsWithTag (tag);
			Array.Sort (gameObjects, CompareGameObjects);
			return gameObjects;
		}

		/// <summary>
		/// Finds the child by tag.
		/// </summary>
		/// <returns>The child by tag.</returns>
		/// <param name="p">parent.</param>
		/// <param name="childTag">Child tag.</param>
		public static Transform FindChildByTag (Transform theParent, string childTag)
		{
			if (string.IsNullOrEmpty (childTag) || theParent == null) {
				return null;
			}
			
			foreach (Transform child in theParent) {
				if (child.CompareTag(childTag)) {
					return child;
				}
			}
			
			return null;
		}

		/// <summary>
		/// Compares the game objects.
		/// </summary>
		/// <returns>The game objects.</returns>
		/// <param name="gameObject1">Game object1.</param>
		/// <param name="gameObject2">Game object2.</param>
		private static int CompareGameObjects (GameObject gameObject1, GameObject gameObject2)
		{
			return gameObject1.name.CompareTo (gameObject2.name);
		}

		/// <summary>
		/// Play the one shot clip.
		/// </summary>
		/// <param name="audioClip">Audio clip.</param>
		/// <param name="postion">Postion.</param>
		/// <param name="volume">Volume.</param>
		public static void PlayOneShotClipAt (AudioClip audioClip, Vector3 postion, float volume)
		{

			if (audioClip == null || volume == 0) {
				return;
			}

			GameObject oneShotAudio = new GameObject ("one shot audio"); 
			oneShotAudio.transform.position = postion; 

			AudioSource tempAudioSource = oneShotAudio.AddComponent<AudioSource> (); //add an audio source
			tempAudioSource.clip = audioClip;//set the audio clip
			tempAudioSource.volume = volume;//set the volume
			tempAudioSource.loop = false;//set loop to false
			tempAudioSource.rolloffMode = AudioRolloffMode.Linear;//linear rolloff mode
			tempAudioSource.Play ();// play audio clip
			GameObject.Destroy (oneShotAudio, audioClip.length); //destroy oneShotAudio gameobject after clip duration
		}

		/// <summary>
		/// Get random color.
		/// </summary>
		/// <returns>The random color.</returns>
		public static Color GetRandomColor ()
		{
			return new Color (UnityEngine.Random.Range (0, 255), UnityEngine.Random.Range (0, 255), UnityEngine.Random.Range (0, 255), 255) / 255.0f;
		}

		/// <summary>
		/// Sets the rect transform as.
		/// </summary>
		/// <param name="rect">Rect.</param>
		/// <param name="target">Target.</param>
		public static void SetRectTransformAs (RectTransform rect, RectTransform target)
		{
			if (rect == null || target == null) {

			}
			rect.position = target.position;
			rect.anchoredPosition3D = target.anchoredPosition3D;
			rect.offsetMax = target.offsetMax;
			rect.offsetMin = target.offsetMin;
			rect.anchorMax = target.anchorMax;
			rect.anchorMin = target.anchorMin;
		}

		/// <summary>
		/// Creates target UI element like the one in the Targets Dialog, Play Confirm Dialog, Right Panel.
		/// </summary>
		/// <returns>New instance of target UI reference.</returns>
		/// <param name="targetUIPrefab">The prefab reference of the Target UI.</param>
		/// <param name="targetUIParent">The Parent of the Target UI .</param>
		/// <param name="childPrefab">The Child/PathObject prefab.</param>
		public static Transform CreateTargetUI(GameObject targetUIPrefab,Transform targetUIParent,GameObject childPrefab) {

			if (targetUIPrefab == null || targetUIParent == null || childPrefab == null) {
				return null;
			}

			//Create Target UI
			GameObject targetUI = GameObject.Instantiate (targetUIPrefab, Vector3.zero, Quaternion.identity);
			targetUI.transform.SetParent (targetUIParent);
			targetUI.transform.localScale = Vector3.one;

			//Create the child(Path Object) of the Target UI
			GameObject child = GameObject.Instantiate (childPrefab, Vector3.zero, Quaternion.identity);
			child.GetComponent<PathObject> ().ReleaseResources ();
			child.transform.SetParent (targetUI.transform);
			child.transform.eulerAngles = new Vector3 (0, 0, 20);
			child.GetComponent<RectTransform> ().SetSiblingIndex (0);

			/*
			 * Create a mask for the child
			child.GetComponent<RectTransform> ().sizeDelta = new Vector2 (65, 65);
			Mask mask = child.AddComponent<Mask> ();
			mask.showMaskGraphic = false;
			Image img = child.AddComponent<Image> ();
			img.sprite = targetUI.GetComponent<Image> ().sprite;
			*/

			//Set the size for your objects inside the stage based on the type
			//You can change the scale as you want based on your PathObject type
			if (child.GetComponent<PathObject> ().type == PathObject.Type.GROUND) {
				child.transform.localScale = new Vector3(0.7f,0.7f,1);
			} else {
				child.transform.localScale = new Vector3(0.55f,0.55f,1);
			}
			return targetUI.transform;
		}


		/// <summary>
		/// Reverse a string.
		/// </summary>
		public static string ReverseString(string s)
		{
			char[] arr = s.ToCharArray();
			Array.Reverse(arr);
			return new string(arr);
		}
	}
}